/**
 * Copyright (c) 2009 Teoti Graphix, LLC See:
 *     http://tkarchitecture.teotigraphix.org
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * @author Michael Schmalle mschmalle@teotigraphix.com
 */
package test.suite.tkaframework.patterns.manager
{

import mx.events.FlexEvent;

import org.flexunit.Assert;
import org.flexunit.async.Async;
import org.fluint.uiImpersonation.UIImpersonator;
import org.teotigraphix.dx.core.dx_internal;

import test.suite.tkaframework.support.component.modelManager.TestComponentModelManager;
import test.suite.tkaframework.support.component.modelManager.TestComponentModelManagerCoreModel;

/**
 * @copyright Teoti Graphix, LLC
 * @author Michael Schmalle
 * @date 08-24-09
 */
public class TC_ModelManager
{
	//--------------------------------------------------------------------------
	//
	//  Protected :: Variables 
	//
	//--------------------------------------------------------------------------
		
	protected var component:TestComponentModelManager;
	
	//--------------------------------------------------------------------------
	//
	//  Public Setup :: Methods 
	//
	//--------------------------------------------------------------------------
	
	[Before(ui,async)]
	public function setUp():void
	{
		component = new TestComponentModelManager();
		Async.proceedOnEvent(this, component, FlexEvent.CREATION_COMPLETE);
		UIImpersonator.addChild( component );
	}
	
	[After]
	public function tearDown():void
	{
		UIImpersonator.removeChild( component );
		component = null;
	}
	
	//--------------------------------------------------------------------------
	//
	//  Public Test :: Methods 
	//
	//--------------------------------------------------------------------------
	
	// The Component to Model Relationship;
	// 
	// > Single property setting.
	//
	// - Model updates the Component at initialization
	//   - updateValueInterestAPI()
	// - Model updates the Component at runtime
	//   - listValueInterests()
	// - Component updates the Model at initialization
	//   - updateValueInterestAPI()
	// - Component updates the Model at runtime
	//   - [ModelBinding]
	// 
	// > coreModel assignment
	// > registerModel() call
	//   > Both of the above trigger updateValueInterestAPI()
	// 
	// toolKitInitialized == false
	// 
	// - Model updates the Component at initialization
	//   - Model.dx_internal::initializeComponent == true
	// - Component updates the Model at initialization
	//   - Model.dx_internal::initializeComponent == false
	// 
	// toolKitInitialized == true
	// 
	// - Model updates the Component at runtime
	//   - model.dx_internal::resetComponent == true
	// - Component updates the Model at runtime
	//   - - model.dx_internal::resetComponent == false
	
	// For now; If no dx_internal properties are set, the Component will
	// ALWAYS update the model when coreModel changes OR registerModel() 
	// is called
	
	[Test]
	/**
	 * Tests the 
	 */
	public function test_base_setup():void
	{
		// test base setting of model properties on component
		
		var o:Object = 
		{
			one:"One",
			two:"Two"
		};
		
		Assert.assertNull( "modelPropertyOne not null", component.modelPropertyOne );
		Assert.assertNull( "modelPropertyTwo not null", component.modelPropertyTwo );
		
		component.modelPropertyOne = o.one;
		component.modelPropertyTwo = o.two;
		
		Assert.assertEquals( "modelPropertyOne not equal", o.one, component.modelPropertyOne );
		Assert.assertEquals( "modelPropertyTwo not equal", o.two, component.modelPropertyTwo );
	}
	
	[Test]
	/**
	 * Tests the whether the Model updates the Component at initialization.
	 * 
	 * Note: This will overwrite MXML properties or an preinitialization
	 * done on the Component after calling new and before parent.addChild().
	 * 
	 * For this to work right now Model.dx_internal::initializeComponent
	 * needs to be set to true.
	 */
	public function test_set_coreModel_initialize_values():void
	{
		var o:Object = 
		{
			one:"One",
			two:"Two"
		};
				
		var mcomponent:TestComponentModelManager = new TestComponentModelManager();
		var core:TestComponentModelManagerCoreModel = new TestComponentModelManagerCoreModel();
		
		core.modelPropertyOne = o.one;
		core.modelPropertyTwo = o.two;
		
		mcomponent.coreModel = core;
		
		Assert.assertNull( "modelPropertyOne not null", mcomponent.modelPropertyOne );
		Assert.assertNull( "modelPropertyTwo not null", mcomponent.modelPropertyTwo );
		
		core.dx_internal::initializeComponent = true;
		
		// calls MM.activateModel() -> MM.updateComponentAPI()
		UIImpersonator.addChild( mcomponent );
		
		Assert.assertNotNull( "modelPropertyOne null", mcomponent.modelPropertyOne );
		Assert.assertNotNull( "modelPropertyTwo null", mcomponent.modelPropertyTwo );
	}
	
	[Test]
	/**
	 * Tests the whether the Model updates the Component at runtime.
	 */
	public function test_set_coreModel_runtime_values():void
	{
		var o:Object = 
		{
			one:"One",
			two:"Two"
		};
				
		var mcomponent:TestComponentModelManager = new TestComponentModelManager();
		var core:TestComponentModelManagerCoreModel = new TestComponentModelManagerCoreModel();
		
		mcomponent.coreModel = core;
		
		UIImpersonator.addChild( mcomponent );
		
		// this will update the component's values with the new model values
		core.modelPropertyOne = o.one;
		core.modelPropertyTwo = o.two;
		
		Assert.assertNotNull( "modelPropertyOne null", mcomponent.modelPropertyOne );
		Assert.assertNotNull( "modelPropertyTwo null", mcomponent.modelPropertyTwo );
		
		Assert.assertEquals( "modelPropertyOne not equal", o.one, mcomponent.modelPropertyOne );
		Assert.assertEquals( "modelPropertyTwo not equal", o.two, mcomponent.modelPropertyTwo );		
	}
	
	
	[Test]
	/**
	 * Tests the whether the Component updates the Model at initialization.
	 */
	public function test_set_component_initialize_values():void
	{
		var o:Object = 
		{
			one:"One",
			two:"Two"
		};
				
		var mcomponent:TestComponentModelManager = new TestComponentModelManager();
		var core:TestComponentModelManagerCoreModel = new TestComponentModelManagerCoreModel();
		
		mcomponent.modelPropertyOne = o.one;
		mcomponent.modelPropertyTwo = o.two;
		
		mcomponent.coreModel = core;
		
		Assert.assertEquals( "c.modelPropertyOne not equal", o.one, mcomponent.modelPropertyOne );
		Assert.assertEquals( "c.modelPropertyTwo not equal", o.two, mcomponent.modelPropertyTwo );
		
		Assert.assertNull( "m.modelPropertyOne not null", core.modelPropertyOne );
		Assert.assertNull( "m.modelPropertyTwo not null", core.modelPropertyTwo );		
		
		// will call updateComponentOrModelAPI() which then syncronizes Model with Component
		UIImpersonator.addChild( mcomponent );
		
		Assert.assertEquals( "m.modelPropertyOne not equal", o.one, core.modelPropertyOne );
		Assert.assertEquals( "m.modelPropertyTwo not equal", o.two, core.modelPropertyTwo );
	}
	
	[Test]
	/**
	 * Tests the whether the Component updates the Model at runtime.
	 */
	public function test_set_component_runtime_values():void
	{
		var o:Object = 
		{
			one:"One",
			two:"Two"
		};
				
		var mcomponent:TestComponentModelManager = new TestComponentModelManager();
		var core:TestComponentModelManagerCoreModel = new TestComponentModelManagerCoreModel();
		
		mcomponent.coreModel = core;
		
		UIImpersonator.addChild( mcomponent );
		
		Assert.assertNull( "m.modelPropertyOne not null", core.modelPropertyOne );
		Assert.assertNull( "m.modelPropertyTwo not null", core.modelPropertyTwo );
		
		mcomponent.modelPropertyOne = o.one;
		mcomponent.modelPropertyTwo = o.two;
		
		Assert.assertEquals( "c.modelPropertyOne not equal", o.one, mcomponent.modelPropertyOne );
		Assert.assertEquals( "c.modelPropertyTwo not equal", o.two, mcomponent.modelPropertyTwo );				
		
		Assert.assertEquals( "m.modelPropertyOne not equal", o.one, core.modelPropertyOne );
		Assert.assertEquals( "m.modelPropertyTwo not equal", o.two, core.modelPropertyTwo );
	}
}
}